Образовательный центр МГТУ им. Н.Э. Баумана
Выполнил: Четвериков А.В.
Краткий план работы:
Оценка точности моделей для прогнозирования свойств
Разработка и обучение модели, рекомендующей соотношение матрица-наполнитель
Оценка точности моделей для рекомендации состава
Разработка приложения с графическим интерфейсом, которое будет выдавать прогноз свойств и рекомендацию состава
# Загрузим необходимые библиотеки и модули
import pathlib #для задания относительного пути к файлам
from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
import seaborn as sns
import plotly.express as px
import sklearn
import scipy
from sklearn.preprocessing import MinMaxScaler
%matplotlib inline
# Определим путь к датасетам
dir_path = pathlib.Path.cwd()
paht_bp = Path(dir_path.parents[0], 'datasets', 'X_bp.xlsx')
paht_nup = Path(dir_path.parents[0], 'datasets', 'X_nup.xlsx')
# так же можно задать путь явно:
# paht_bp = r"C:\ ... \vkr\datasets\X_bp.xlsx"
# paht_nup = r"C:\ ... \vkr\datasets\X_nup.xlsx"
#Загрузим первый датасет
df_bp = pd.read_excel(paht_bp)
df_bp.shape
(1023, 11)
#Отобразим первые 5 строк первого датасета
df_bp.head()
| Unnamed: 0 | Соотношение матрица-наполнитель | Плотность, кг/м3 | модуль упругости, ГПа | Количество отвердителя, м.% | Содержание эпоксидных групп,%_2 | Температура вспышки, С_2 | Поверхностная плотность, г/м2 | Модуль упругости при растяжении, ГПа | Прочность при растяжении, МПа | Потребление смолы, г/м2 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.0 | 1.857143 | 2030.0 | 738.736842 | 30.00 | 22.267857 | 100.000000 | 210.0 | 70.0 | 3000.0 | 220.0 |
| 1 | 1.0 | 1.857143 | 2030.0 | 738.736842 | 50.00 | 23.750000 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 |
| 2 | 2.0 | 1.857143 | 2030.0 | 738.736842 | 49.90 | 33.000000 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 |
| 3 | 3.0 | 1.857143 | 2030.0 | 738.736842 | 129.00 | 21.250000 | 300.000000 | 210.0 | 70.0 | 3000.0 | 220.0 |
| 4 | 4.0 | 2.771331 | 2030.0 | 753.000000 | 111.86 | 22.267857 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 |
#Удалим первый столбец, так как он не несет никакой информации
df_bp.drop(['Unnamed: 0'], axis=1, inplace=True)
df_bp.head()
| Соотношение матрица-наполнитель | Плотность, кг/м3 | модуль упругости, ГПа | Количество отвердителя, м.% | Содержание эпоксидных групп,%_2 | Температура вспышки, С_2 | Поверхностная плотность, г/м2 | Модуль упругости при растяжении, ГПа | Прочность при растяжении, МПа | Потребление смолы, г/м2 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1.857143 | 2030.0 | 738.736842 | 30.00 | 22.267857 | 100.000000 | 210.0 | 70.0 | 3000.0 | 220.0 |
| 1 | 1.857143 | 2030.0 | 738.736842 | 50.00 | 23.750000 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 |
| 2 | 1.857143 | 2030.0 | 738.736842 | 49.90 | 33.000000 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 |
| 3 | 1.857143 | 2030.0 | 738.736842 | 129.00 | 21.250000 | 300.000000 | 210.0 | 70.0 | 3000.0 | 220.0 |
| 4 | 2.771331 | 2030.0 | 753.000000 | 111.86 | 22.267857 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 |
df_bp.shape
(1023, 10)
# Загрузим второй датасет
df_nup = pd.read_excel(paht_nup)
df_nup.shape
(1040, 4)
#Посмотрим на первые 5 строк второго датасета
df_nup.head()
| Unnamed: 0 | Угол нашивки, град | Шаг нашивки | Плотность нашивки | |
|---|---|---|---|---|
| 0 | 0.0 | 0.0 | 4.0 | 57.0 |
| 1 | 1.0 | 0.0 | 4.0 | 60.0 |
| 2 | 2.0 | 0.0 | 4.0 | 70.0 |
| 3 | 3.0 | 0.0 | 5.0 | 47.0 |
| 4 | 4.0 | 0.0 | 5.0 | 57.0 |
#Удалим первый столбец, так как он не несет никакой информации
df_nup.drop(['Unnamed: 0'], axis=1, inplace=True)
df_nup.head()
| Угол нашивки, град | Шаг нашивки | Плотность нашивки | |
|---|---|---|---|
| 0 | 0.0 | 4.0 | 57.0 |
| 1 | 0.0 | 4.0 | 60.0 |
| 2 | 0.0 | 4.0 | 70.0 |
| 3 | 0.0 | 5.0 | 47.0 |
| 4 | 0.0 | 5.0 | 57.0 |
df_nup.shape
(1040, 3)
# Объединяем два датасета в один по типу INNER.
df = pd.merge(df_bp, df_nup, left_index = True, right_index = True, how = 'inner')
df.head()
| Соотношение матрица-наполнитель | Плотность, кг/м3 | модуль упругости, ГПа | Количество отвердителя, м.% | Содержание эпоксидных групп,%_2 | Температура вспышки, С_2 | Поверхностная плотность, г/м2 | Модуль упругости при растяжении, ГПа | Прочность при растяжении, МПа | Потребление смолы, г/м2 | Угол нашивки, град | Шаг нашивки | Плотность нашивки | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1.857143 | 2030.0 | 738.736842 | 30.00 | 22.267857 | 100.000000 | 210.0 | 70.0 | 3000.0 | 220.0 | 0.0 | 4.0 | 57.0 |
| 1 | 1.857143 | 2030.0 | 738.736842 | 50.00 | 23.750000 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 | 0.0 | 4.0 | 60.0 |
| 2 | 1.857143 | 2030.0 | 738.736842 | 49.90 | 33.000000 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 | 0.0 | 4.0 | 70.0 |
| 3 | 1.857143 | 2030.0 | 738.736842 | 129.00 | 21.250000 | 300.000000 | 210.0 | 70.0 | 3000.0 | 220.0 | 0.0 | 5.0 | 47.0 |
| 4 | 2.771331 | 2030.0 | 753.000000 | 111.86 | 22.267857 | 284.615385 | 210.0 | 70.0 | 3000.0 | 220.0 | 0.0 | 5.0 | 57.0 |
df.shape
(1023, 13)
#Просмотрим информацию о датасете
df.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 1023 entries, 0 to 1022 Data columns (total 13 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Соотношение матрица-наполнитель 1023 non-null float64 1 Плотность, кг/м3 1023 non-null float64 2 модуль упругости, ГПа 1023 non-null float64 3 Количество отвердителя, м.% 1023 non-null float64 4 Содержание эпоксидных групп,%_2 1023 non-null float64 5 Температура вспышки, С_2 1023 non-null float64 6 Поверхностная плотность, г/м2 1023 non-null float64 7 Модуль упругости при растяжении, ГПа 1023 non-null float64 8 Прочность при растяжении, МПа 1023 non-null float64 9 Потребление смолы, г/м2 1023 non-null float64 10 Угол нашивки, град 1023 non-null float64 11 Шаг нашивки 1023 non-null float64 12 Плотность нашивки 1023 non-null float64 dtypes: float64(13) memory usage: 111.9 KB
# Все переменные содержат значения float64, качественные характеристики отсутствуют. Пропусков не имеется.
# Ни одна из записей не является NaN, очистка не требуется. Объединенный файл имеет всего 1023 строки.
#Посмотрим уникальные значения в датасете
df.nunique()
Соотношение матрица-наполнитель 1014 Плотность, кг/м3 1013 модуль упругости, ГПа 1020 Количество отвердителя, м.% 1005 Содержание эпоксидных групп,%_2 1004 Температура вспышки, С_2 1003 Поверхностная плотность, г/м2 1004 Модуль упругости при растяжении, ГПа 1004 Прочность при растяжении, МПа 1004 Потребление смолы, г/м2 1003 Угол нашивки, град 2 Шаг нашивки 989 Плотность нашивки 988 dtype: int64
#В основном в каждом столбце содержатся только уникальные значения, но в столбце "Угол нашивки" всего 2 значения.
# Сохраним полученный датасет для дальнейшей работы
paht_out = Path(dir_path.parents[0], 'datasets', 'out.xlsx')
df.to_excel(paht_out)
#Изучим описательную статистику
df.describe().T
| count | mean | std | min | 25% | 50% | 75% | max | |
|---|---|---|---|---|---|---|---|---|
| Соотношение матрица-наполнитель | 1023.0 | 2.930366 | 0.913222 | 0.389403 | 2.317887 | 2.906878 | 3.552660 | 5.591742 |
| Плотность, кг/м3 | 1023.0 | 1975.734888 | 73.729231 | 1731.764635 | 1924.155467 | 1977.621657 | 2021.374375 | 2207.773481 |
| модуль упругости, ГПа | 1023.0 | 739.923233 | 330.231581 | 2.436909 | 500.047452 | 739.664328 | 961.812526 | 1911.536477 |
| Количество отвердителя, м.% | 1023.0 | 110.570769 | 28.295911 | 17.740275 | 92.443497 | 110.564840 | 129.730366 | 198.953207 |
| Содержание эпоксидных групп,%_2 | 1023.0 | 22.244390 | 2.406301 | 14.254985 | 20.608034 | 22.230744 | 23.961934 | 33.000000 |
| Температура вспышки, С_2 | 1023.0 | 285.882151 | 40.943260 | 100.000000 | 259.066528 | 285.896812 | 313.002106 | 413.273418 |
| Поверхностная плотность, г/м2 | 1023.0 | 482.731833 | 281.314690 | 0.603740 | 266.816645 | 451.864365 | 693.225017 | 1399.542362 |
| Модуль упругости при растяжении, ГПа | 1023.0 | 73.328571 | 3.118983 | 64.054061 | 71.245018 | 73.268805 | 75.356612 | 82.682051 |
| Прочность при растяжении, МПа | 1023.0 | 2466.922843 | 485.628006 | 1036.856605 | 2135.850448 | 2459.524526 | 2767.193119 | 3848.436732 |
| Потребление смолы, г/м2 | 1023.0 | 218.423144 | 59.735931 | 33.803026 | 179.627520 | 219.198882 | 257.481724 | 414.590628 |
| Угол нашивки, град | 1023.0 | 44.252199 | 45.015793 | 0.000000 | 0.000000 | 0.000000 | 90.000000 | 90.000000 |
| Шаг нашивки | 1023.0 | 6.899222 | 2.563467 | 0.000000 | 5.080033 | 6.916144 | 8.586293 | 14.440522 |
| Плотность нашивки | 1023.0 | 57.153929 | 12.350969 | 0.000000 | 49.799212 | 57.341920 | 64.944961 | 103.988901 |
# Проверим есть ли пропущенные данные
df.isnull().sum()
Соотношение матрица-наполнитель 0 Плотность, кг/м3 0 модуль упругости, ГПа 0 Количество отвердителя, м.% 0 Содержание эпоксидных групп,%_2 0 Температура вспышки, С_2 0 Поверхностная плотность, г/м2 0 Модуль упругости при растяжении, ГПа 0 Прочность при растяжении, МПа 0 Потребление смолы, г/м2 0 Угол нашивки, град 0 Шаг нашивки 0 Плотность нашивки 0 dtype: int64
#Построим тепловую карту пропущенных данных
cols = df.columns
colours = ["blue", "purple"]
sns.set_palette(colours)
sns.heatmap(df[cols].isnull(), cmap = sns.color_palette())
<AxesSubplot:>
# Проверим датасет на дубликаты
df.duplicated().sum()
0
#Посмотрим еще раз медианное и среднее значение
df.describe().loc[['mean', '50%']].T
| mean | 50% | |
|---|---|---|
| Соотношение матрица-наполнитель | 2.930366 | 2.906878 |
| Плотность, кг/м3 | 1975.734888 | 1977.621657 |
| модуль упругости, ГПа | 739.923233 | 739.664328 |
| Количество отвердителя, м.% | 110.570769 | 110.564840 |
| Содержание эпоксидных групп,%_2 | 22.244390 | 22.230744 |
| Температура вспышки, С_2 | 285.882151 | 285.896812 |
| Поверхностная плотность, г/м2 | 482.731833 | 451.864365 |
| Модуль упругости при растяжении, ГПа | 73.328571 | 73.268805 |
| Прочность при растяжении, МПа | 2466.922843 | 2459.524526 |
| Потребление смолы, г/м2 | 218.423144 | 219.198882 |
| Угол нашивки, град | 44.252199 | 0.000000 |
| Шаг нашивки | 6.899222 | 6.916144 |
| Плотность нашивки | 57.153929 | 57.341920 |
# медианное и среднее значение каждой переменной довольно близки друг к другу, кроме угла нашивки
plt.figure(figsize = (16,10))
ax = sns.boxplot(data = df)
ax.set_xticklabels(ax.get_xticklabels(),rotation=90);
# Вычислим коэффициенты корреляции.
df.corr().style.background_gradient(cmap='YlOrBr')
| Соотношение матрица-наполнитель | Плотность, кг/м3 | модуль упругости, ГПа | Количество отвердителя, м.% | Содержание эпоксидных групп,%_2 | Температура вспышки, С_2 | Поверхностная плотность, г/м2 | Модуль упругости при растяжении, ГПа | Прочность при растяжении, МПа | Потребление смолы, г/м2 | Угол нашивки, град | Шаг нашивки | Плотность нашивки | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Соотношение матрица-наполнитель | 1.000000 | 0.003841 | 0.031700 | -0.006445 | 0.019766 | -0.004776 | -0.006272 | -0.008411 | 0.024148 | 0.072531 | -0.031073 | 0.036437 | -0.004652 |
| Плотность, кг/м3 | 0.003841 | 1.000000 | -0.009647 | -0.035911 | -0.008278 | -0.020695 | 0.044930 | -0.017602 | -0.069981 | -0.015937 | -0.068474 | -0.061015 | 0.080304 |
| модуль упругости, ГПа | 0.031700 | -0.009647 | 1.000000 | 0.024049 | -0.006804 | 0.031174 | -0.005306 | 0.023267 | 0.041868 | 0.001840 | -0.025417 | -0.009875 | 0.056346 |
| Количество отвердителя, м.% | -0.006445 | -0.035911 | 0.024049 | 1.000000 | -0.000684 | 0.095193 | 0.055198 | -0.065929 | -0.075375 | 0.007446 | 0.038570 | 0.014887 | 0.017248 |
| Содержание эпоксидных групп,%_2 | 0.019766 | -0.008278 | -0.006804 | -0.000684 | 1.000000 | -0.009769 | -0.012940 | 0.056828 | -0.023899 | 0.015165 | 0.008052 | 0.003022 | -0.039073 |
| Температура вспышки, С_2 | -0.004776 | -0.020695 | 0.031174 | 0.095193 | -0.009769 | 1.000000 | 0.020121 | 0.028414 | -0.031763 | 0.059954 | 0.020695 | 0.025795 | 0.011391 |
| Поверхностная плотность, г/м2 | -0.006272 | 0.044930 | -0.005306 | 0.055198 | -0.012940 | 0.020121 | 1.000000 | 0.036702 | -0.003210 | 0.015692 | 0.052299 | 0.038332 | -0.049923 |
| Модуль упругости при растяжении, ГПа | -0.008411 | -0.017602 | 0.023267 | -0.065929 | 0.056828 | 0.028414 | 0.036702 | 1.000000 | -0.009009 | 0.050938 | 0.023003 | -0.029468 | 0.006476 |
| Прочность при растяжении, МПа | 0.024148 | -0.069981 | 0.041868 | -0.075375 | -0.023899 | -0.031763 | -0.003210 | -0.009009 | 1.000000 | 0.028602 | 0.023398 | -0.059547 | 0.019604 |
| Потребление смолы, г/м2 | 0.072531 | -0.015937 | 0.001840 | 0.007446 | 0.015165 | 0.059954 | 0.015692 | 0.050938 | 0.028602 | 1.000000 | -0.015334 | 0.013394 | 0.012239 |
| Угол нашивки, град | -0.031073 | -0.068474 | -0.025417 | 0.038570 | 0.008052 | 0.020695 | 0.052299 | 0.023003 | 0.023398 | -0.015334 | 1.000000 | 0.023616 | 0.107947 |
| Шаг нашивки | 0.036437 | -0.061015 | -0.009875 | 0.014887 | 0.003022 | 0.025795 | 0.038332 | -0.029468 | -0.059547 | 0.013394 | 0.023616 | 1.000000 | 0.003487 |
| Плотность нашивки | -0.004652 | 0.080304 | 0.056346 | 0.017248 | -0.039073 | 0.011391 | -0.049923 | 0.006476 | 0.019604 | 0.012239 | 0.107947 | 0.003487 | 1.000000 |
# Явной зависимости между переменными не наблюдается
# Построим гистограммы распределения каждого признака
vertic = 7 # количество графиков по вертикали
horiz = 2 # количество графиков по горизонтали
count = 1 # порядковый номер графика
fig = plt.figure(figsize = (15,30))
fig.suptitle('Гистограммы переменных', y = 0.91 ,
fontsize = 30)
for column in df.columns:
ax = plt.subplot(vertic, horiz, count, box_aspect= 0.48)
res = sns.histplot(data = df[column], kde=True, color = "purple")
ax.set_xlabel(None)
ax.set_ylabel(None)
ax.set_title(column, y = 1.0, size = 15)
count += 1
# график qq
vertic = 7 # количество графиков по вертикали
horiz = 2 # количество графиков по горизонтали
count = 1 # порядковый номер графика
fig = plt.figure(figsize = (24,50))
fig.suptitle('Графики вероятностей выборочных данных относительно квантилей нормального распределения', y = 0.91 ,
fontsize = 30)
for column in df.columns:
ax = plt.subplot(vertic, horiz, count, box_aspect= 0.48)
res = scipy.stats.probplot(df[column], plot = plt)
ax.set_xlabel("Теоретические квантили", fontsize = 15)
ax.set_ylabel("Упорядоченные значения", fontsize = 15)
ax.set_title(column, y = 1.0, size = 15)
count += 1
# Данные стремятся к нормальному распределению практически везде,
# кроме угла нашивки, имеющим только 2 значения, с которым мы уже поработали ранее.
# Построим ящики с усами для каждого признака отдельно
vertic = 7 # количество графиков по вертикали
horiz = 2 # количество графиков по горизонтали
count = 1 # порядковый номер графика
fig = plt.figure(figsize = (20,35))
fig.suptitle('Диаграммы "ящики с усами"', y = 0.91 ,
fontsize = 30)
for column in df.columns:
ax = plt.subplot(vertic, horiz, count, box_aspect= 0.40)
res = sns.boxplot(x = df[column], color = "purple");
ax.set_xlabel(None)
ax.set_ylabel(None)
ax.set_title(column, y = 1.0, size = 15)
count += 1
# "Ящики с усами" показывают наличие выбросов во всех столбцах, кроме углов нашивки
# Построим попарные графики рассеяния
g = sns.PairGrid(df[df.columns])
g.map(sns.scatterplot, color = 'purple')
g.map_upper(sns.scatterplot, color = 'purple')
g.map_lower(sns.kdeplot, color = 'purple')
plt.show
<function matplotlib.pyplot.show(close=None, block=None)>
# Попарные графики рассеяния точек так же не показывают какой-либо зависимости между данными.
# Зависимость между показателями не линейная, явная взаимосвязь отсутствует, необходимо использовать несколько показателей.
# На графиках можно наблюдать выбросы, потому что некоторые точки располагаются далеко от общего облака
Вывод:
на данном этапе работы на сырых данных мы наблюдаем выбросы в каждом столбце, кроме столбца "Угол нашивки" и корреляция входных переменных очень слабая.